﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;

namespace ClassLibrary
{
    public class LambdaLifter
    {
        private FileStream _fileStream;
        private string _path;
        private string result = "";
        public int _n = 0; //x axe nombre de colonne
        public int _m = 0; //y axe nombre de ligne
        public char[][] _map;
        public char[][] _mapTemp;
        public LambdaLifter(string path)
        {
            _fileStream = new FileStream(path, FileMode.Open, FileAccess.Read);
            _path = path;
            InitializeMap();
        }

        public void ChangeTheMap(string path)
        {
            _fileStream = new FileStream(path, FileMode.Open, FileAccess.Read);
            _path = path;
            InitializeMap();
        }


        public void ChangeTheMap(int i)
        {

            var path = @"C:\Users\Romain\documents\visual studio 2010\Projects\ProjetTest\ClassLibrary\Resource\contest" +
                i + ".map";

            _fileStream = new FileStream(path, FileMode.Open, FileAccess.Read);
            _path = path;
            InitializeMap();
        }


        public void PrintMap()
        {
            using (var sr = new StreamReader(_path))
            {
                string line;
                while ((line = sr.ReadLine()) != null)
                {
                    Console.WriteLine(line);
                }
            }
        }

        public void PrintMapFromArray()
        {

            for (int y = _m - 1; y >= 0; y--)
            {
                for (int x = 0; x < _n; x++)
                {
                    Console.Write(_map[y][x]);
                }
                Console.Write(Environment.NewLine);
            }
            //Console.WriteLine(String.Format("Nombre de colonnes : {0}", _n));
            //Console.WriteLine(String.Format("Nombre de lignes : {0}", _m));
        }


        public void InitializeMap()
        {
            _n = 0;
            _m = 0;
            var map = new List<List<char>>();
            using (var sr = new StreamReader(_path))
            {
                string line;
                while ((line = sr.ReadLine()) != null)
                {
                    _m++;
                    var lineList = line.ToCharArray().ToList();
                    if (lineList.Count() > _n)
                    {
                        _n = lineList.Count();
                    }
                    map.Add(lineList);
                }
            }
            _map = new char[_m][];

            int y = _m - 1;
            foreach (var l in map)
            {
                _map[y] = new char[_n];
                _map[y] = l.ToArray();
                y--;
            }
        }

        public void MapUpdate()
        {
            CopyMap(_map, out _mapTemp);
            bool noLampdasRemaining = true;
            for (int y = 0; y < _m; y++)
            {
                for (int x = 0; x < _n; x++)
                {
                    if (_mapTemp[y][x] == '\\')
                    {
                        noLampdasRemaining = false;
                    }
                }
            }

            for (int x = 0; x < _n; x++)
            {
                if (_mapTemp[0][x] == 'L' && noLampdasRemaining)
                {
                    _map[0][x] = 'O';
                }
            }


            for (int y = 1; y < _m; y++)
            {
                for (int x = 0; x < _n - 1; x++)
                {
                    if (_mapTemp[y][x] == '*' && _mapTemp[y - 1][x] == ' ')
                    {
                        _map[y][x] = ' ';
                        _map[y - 1][x] = '*';
                    }
                    if (_mapTemp[y][x] == '*' && _mapTemp[y - 1][x] == '*' && _mapTemp[y][x + 1] == ' ' &&
                        _mapTemp[y - 1][x + 1] == ' ')
                    {
                        _map[y][x] = ' ';
                        _map[y - 1][x + 1] = '*';
                    }
                    if (_mapTemp[y][x] == '*' && _mapTemp[y - 1][x] == '*' &&
                        (_mapTemp[y][x + 1] != ' ' || _mapTemp[y - 1][x + 1] != ' ') && _mapTemp[y][x - 1] == ' ' &&
                        _mapTemp[y - 1][x - 1] == ' ')
                    {
                        _map[y][x] = ' ';
                        _map[y - 1][x - 1] = '*';
                    }
                    if (_mapTemp[y][x] == '*' && _mapTemp[y - 1][x] == '\\' && _mapTemp[y][x + 1] == ' ' &&
                        _mapTemp[y - 1][x + 1] == ' ')
                    {
                        _map[y][x] = ' ';
                        _map[y - 1][x + 1] = '*';
                    }

                    if (_mapTemp[y][x] == 'L' && noLampdasRemaining)
                    {
                        _map[y][x] = 'O';
                    }
                }
            }
            for (int y = 1; y < _m; y++)
            {
                var x = _n - 1;
                if (_mapTemp[y][x] == '*' && _mapTemp[y - 1][x] == ' ')
                {
                    _map[y][x] = ' ';
                    _map[y - 1][x] = '*';
                }
            }
        }




        public void MapUpdate(ref char[][] map) // il faut définir des bornes de ce que l'on veut mettre à jour
        {
            char[][] mapTemp;
            CopyMap(map, out mapTemp);
            bool noLampdasRemaining = true;
            for (int y = 0; y < _m; y++)
            {
                for (int x = 0; x < _n; x++)
                {
                    if (mapTemp[y][x] == '\\')
                    {
                        noLampdasRemaining = false;
                    }
                }
            }

            for (int x = 0; x < _n; x++)
            {
                if (mapTemp[0][x] == 'L' && noLampdasRemaining)
                {
                    map[0][x] = 'O';
                }
            }


            for (int y = 1; y < _m; y++)
            {
                for (int x = 0; x < _n - 1; x++)
                {
                    if (mapTemp[y][x] == '*' && mapTemp[y - 1][x] == ' ')
                    {
                        map[y][x] = ' ';
                        map[y - 1][x] = '*';
                    }
                    if (mapTemp[y][x] == '*' && mapTemp[y - 1][x] == '*' && mapTemp[y][x + 1] == ' ' &&
                        mapTemp[y - 1][x + 1] == ' ')
                    {
                        map[y][x] = ' ';
                        map[y - 1][x + 1] = '*';
                    }
                    if (mapTemp[y][x] == '*' && mapTemp[y - 1][x] == '*' &&
                        (mapTemp[y][x + 1] != ' ' || mapTemp[y - 1][x + 1] != ' ') && mapTemp[y][x - 1] == ' ' &&
                        mapTemp[y - 1][x - 1] == ' ')
                    {
                        map[y][x] = ' ';
                        map[y - 1][x - 1] = '*';
                    }
                    if (mapTemp[y][x] == '*' && mapTemp[y - 1][x] == '\\' && mapTemp[y][x + 1] == ' ' &&
                        mapTemp[y - 1][x + 1] == ' ')
                    {
                        map[y][x] = ' ';
                        map[y - 1][x + 1] = '*';
                    }

                    if (mapTemp[y][x] == 'L' && noLampdasRemaining)
                    {
                        map[y][x] = 'O';
                    }
                }
            }
            for (int y = 1; y < _m; y++)
            {
                var x = _n - 1;
                if (mapTemp[y][x] == '*' && mapTemp[y - 1][x] == ' ')
                {
                    map[y][x] = ' ';
                    map[y - 1][x] = '*';
                }
            }
        }


        public List<char> Successeurs(int x, int y)  // à partir de 0 !!!
        {

            //Vérifier que état à la !( finy + 2 == '*' && finy + 1 == ' ')
            var succ = new List<char>();

            if (y < _m - 1)
            {
                if (IsValidMove(x, y + 1) && !EcraseParRoche(x, y + 1))
                {
                    succ.Add('U');
                }
            }
            if (y > 0)
            {
                if (IsValidMove(x, y - 1) && !EcraseParRoche(x, y - 1))
                {
                    succ.Add('D');
                }
            }
            if (x < _n - 2)
            {
                if (_map[y][x + 1] == '*' && _map[y][x + 2] == ' ')
                {
                    succ.Add('R');
                }
                else
                {
                    if (IsValidMove(x + 1, y) && !EcraseParRoche(x + 1, y))
                    {
                        succ.Add('R');
                    }
                }
            }
            else
            {
                if (x == _n - 2)
                {
                    if (IsValidMove(x + 1, y) && !EcraseParRoche(x + 1, y))
                    {
                        succ.Add('R');
                    }
                }

            }

            if (x > 1)
            {
                if (_map[y][x - 1] == '*' && _map[y][x - 2] == ' ')
                {
                    succ.Add('L');
                }
                else
                {
                    if (IsValidMove(x - 1, y) && !EcraseParRoche(x - 1, y))
                    {
                        succ.Add('L');
                    }
                }
            }
            else
            {
                if (x == 1)
                {
                    if (IsValidMove(0, y) && !EcraseParRoche(0, y))
                    {
                        succ.Add('L');
                    }
                }
            }
            return succ;
        }


        public bool IsValidMove(int x, int y)
        {
            return _map[y][x] == ' ' || _map[y][x] == '.' || _map[y][x] == '\\' || _map[y][x] == 'O';
        }

        public bool EcraseParRoche(int x, int y)
        {
            if (y < _m - 1)
            {
                char p = _map[y + 1][x];
                if (p != '*')
                {
                    CopyMap(_map, out _mapTemp);
                    MapUpdate(ref _mapTemp);
                    if (_mapTemp[y + 1][x] == '*')
                        return true;
                }
            }
            return false;
        }


        public void CopyMap(char[][] map1, out char[][] map2)
        {
            map2 = new char[_m][];
            for (int y = 0; y < _m; y++)
            {
                map2[y] = new char[_n];
                for (int x = 0; x < _n; x++)
                {
                    map2[y][x] = map1[y][x];
                }
            }
        }



        public void FindR(out int rx, out int ry)
        {
            for (int y = 0; y < _m; y++)
            {
                for (int x = 0; x < _n; x++)
                {
                    if (_map[y][x] == 'R')
                    {
                        rx = x;
                        ry = y;
                        return;
                    }
                }
            }
            rx = 0;
            ry = 0;
        }


    }
}
